package com.feeyo.groundservice.usbserial

import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.usb.UsbManager
import android.os.Build
import android.provider.MediaStore.Audio.Radio
import androidx.activity.ComponentActivity
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.lifecycleScope
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialPort
import com.hoho.android.usbserial.driver.UsbSerialProber
import com.hoho.android.usbserial.util.SerialInputOutputManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.io.IOException
import java.lang.Exception
import java.lang.ref.WeakReference
import java.nio.charset.Charset

/**
 *作者：70893 on 2024-11-11
 *描述：如果不方便继承BaseUsbSerialActivity，可以使用辅助工具类挂载到自己的Activity中
 */
object UsbSerialImp : UsbSerialLifecycle, SerialInputOutputManager.Listener {

    private val GRANT_USB = "GRANT_USB"

    private lateinit var usbManager: UsbManager
    private lateinit var activity: WeakReference<ComponentActivity>
    private var packageName = ""
    private var ACTION_GRANT_USB = "$packageName.$GRANT_USB"
    private lateinit var scope: LifecycleCoroutineScope

    @Volatile
    private var connected = false

    @Volatile
    private var canEnable = false//是否准备好连接了，确定在哪一个页面使用初始化

    private var usbSerialPort: UsbSerialPort? = null
    private var usbPermission = UsbPermission.Unknown
    private var usbCallback: UsbCallback? = null
    private var baudRate = 115200// 波特率,太小了 接收字符串会分几次
    private var readTimeOut = 2000//读超时时间，单位ms
    private var deviceId: Int? = null// 设备id
    private var position = 0//序号


    // 串口数据接收
    private var withIoManager = true
    private var usbIoManager: SerialInputOutputManager? = null

    private val broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            if (canEnable && ACTION_GRANT_USB == intent.action) {
                usbPermission =
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
                        UsbPermission.Granted else UsbPermission.Denied

                usbCallback?.onLog(usbPermission.name)
                //授权有返回值的时候，再次尝试连接
                connect()
            }
        }
    }

    override fun init(activity: ComponentActivity) {
        this.activity = WeakReference(activity)
        this.scope = activity.lifecycleScope
    }

    override fun onCreate() {
        require(::activity.isInitialized) {
            "需要一个上下文，请调用init(activity: Activity)"
        }
        usbManager = activity.get()!!.getSystemService(Context.USB_SERVICE) as UsbManager
    }

    override fun onStart() {
        ContextCompat.registerReceiver(
            activity.get()!!, broadcastReceiver,
            IntentFilter(ACTION_GRANT_USB),
            ContextCompat.RECEIVER_NOT_EXPORTED
        )
        usbCallback?.onLog("注册广播")
    }

    override fun onStop() {
        activity.get()!!.unregisterReceiver(broadcastReceiver)
        usbCallback?.onLog("注销广播")
    }

    override fun onResume() {
        if (!connected && (usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted)) {
            require(packageName.isNotEmpty()) {
                "请先设置包名"
            }
            connect()
        }
    }

    override fun onPause() {
        if (connected) {
            disconnect()
        }
    }

    override fun onDestroy() {
        activity.clear()
        usbCallback?.onLog("释放资源")
        usbCallback = null
        deviceId = null
        usbSerialPort = null
        scope.cancel("页面销毁")
    }

    override fun onNewData(data: ByteArray) {
        //接收到对方发送来的数据
        receive(data)
    }

    override fun onRunError(e: Exception) {
        scope.launch(Dispatchers.Main) {
            usbCallback?.onLog("连接丢失：${e.message}")
            disconnect()
        }
    }

    /**是否连接状态**/
    fun isConnected() = connected

    /**设置波特率
     *
     * @param baudRate 波特率，一般默认115200，太小了 接收字符串会分几次
     * **/
    fun setBaudRate(baudRate: Int): UsbSerialImp {
        this.baudRate = baudRate

        return this
    }

    /**设置设备id
     * @param deviceId 设备id 需要连接的usb设备id，一般用在有多个设备的时候
     * **/
    fun setDeviceId(deviceId: Int, position: Int): UsbSerialImp {
        this.deviceId = deviceId
        this.position = position

        return this
    }

    /**设置Action名称
     * @param appPackageName 包名, 一般用于广播过滤
     * **/
    fun setPackage(appPackageName: String): UsbSerialImp {
        this.packageName = appPackageName
        this.ACTION_GRANT_USB = "$appPackageName.$GRANT_USB"

        return this
    }

    /**设置回调监听器
     * @param usbCallback 回调监听器
     * **/
    fun setUsbCallback(usbCallback: UsbCallback): UsbSerialImp {
        this.usbCallback = usbCallback

        return this
    }

    /**是否开启数据接收
     * @param withIoManager 是否开启数据接收监听，默认
     * @param readTimeOut 读超时时间，单位ms
     * **/
    fun setWithIoManager(withIoManager: Boolean, readTimeOut: Int = 2000): UsbSerialImp {
        this.withIoManager = withIoManager
        this.readTimeOut = readTimeOut
        return this
    }


    /**是否开启连接状态
     * @param enable 是否开启连接状态，默认false，需要手动调用setCanEnable(true)，防止初始化自动连接
     * **/
    fun setCanEnable(enable: Boolean) {
        canEnable = enable
    }

    /**发送数据
     *
     * @param data 要发送的数据
     * @param charset 编码格式，默认utf-8
     * **/
    fun sendData(data: String, writeTimeout: Int = 2000, charset: Charset = Charsets.UTF_8) {
        if (!connected) {
            usbCallback?.onLog("设备已断开，重新连接设备")
            connect()
            return
        }
        usbCallback?.onSend(data)
        usbCallback?.onLog("发送数据：$data")
        usbSerialPort?.let {
            if (it.isOpen) {
                it.write(data.toByteArray(charset), writeTimeout)
            } else {
                usbCallback?.onLog("设备已断开，重新连接设备")
                connect()
            }
        }
    }

    private fun connect() {
        //如果没有指定连接设备，取默认的第一个设备
        val driver = deviceId?.let { id ->
            usbManager.deviceList.values.first { it.deviceId == id }?.let {
                UsbSerialProber.getDefaultProber().probeDevice(it)
            }
        } ?: findFirstUsbSerialDriver()

        driver ?: run {
            usbCallback?.onLog("没有发现串口设备")
            usbCallback?.onNotifyUser("没有发现串口设备")
            return
        }
        if (usbManager.hasPermission(driver.device)) {
            usbSerialPort = driver.ports[position]
            usbCallback?.onLog("准备连接的设备信息：${driver.ports}")
            usbManager.openDevice(driver.device)?.apply {
                usbCallback?.onLog("开始连接")
                usbCallback?.onConnect()
                try {
                    usbSerialPort?.open(this)
                    usbSerialPort?.setParameters(
                        baudRate,
                        UsbSerialPort.DATABITS_8,
                        UsbSerialPort.STOPBITS_1,
                        UsbSerialPort.PARITY_NONE
                    )
                    usbSerialPort?.dtr = true
                } catch (e: Exception) {
                    usbCallback?.onLog("打开失败：${e.message}")
                    disconnect()
                }

                connected = true
                usbCallback?.onLog("连接成功")
                usbCallback?.onSuccess()
                if (usbSerialPort == null) {
                    usbCallback?.onLog("没有usb端口")
                    return
                }
                //是否开启数据接收
                if (withIoManager) {
                    usbIoManager = SerialInputOutputManager(usbSerialPort, this@UsbSerialImp)
                    usbIoManager?.apply {
                        this.readTimeout = readTimeOut//读超时默认2s
                        start()//开启数据接收线程
                    }
                }
            } ?: run { usbCallback?.onLog("打开usb设备失败") }
        } else {
            usbCallback?.onLog("没有usb串口权限，准备请求权限")
            val flag =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_MUTABLE else 0
            Intent(ACTION_GRANT_USB).apply {
                setPackage(packageName)
                val usbPermissionIntent =
                    PendingIntent.getBroadcast(activity.get(), 0, this, flag)

                usbPermission = UsbPermission.Requested
                usbManager.requestPermission(driver.device, usbPermissionIntent)
            }
        }
    }

    private fun disconnect() {
        connected = false
        usbCallback?.onDisconnect()
        usbCallback?.onLog("断开连接")
        usbIoManager?.apply {
            listener = null
            stop()
        }
        usbIoManager = null
        try {
            usbSerialPort?.close()
        } catch (e: IOException) {
            usbSerialPort = null
        }

    }

    //发现串口，返回第一个
    private fun findFirstUsbSerialDriver(): UsbSerialDriver? {
        val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager)
        availableDrivers.forEach {
            usbCallback?.onLog("发现串口：${it.device} ${it.ports}")
        }
        return if (availableDrivers.isNotEmpty())
            availableDrivers[0]
        else
            null
    }


    private fun receive(data: ByteArray) {
        scope.launch(Dispatchers.Main) {
            usbCallback?.onReceive(data)
            usbCallback?.onLog("接收到数据：${data.decodeToString()}")
        }
    }
}